package com.hoas.api.client;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hoas.api.encrypt.EncryptUtil;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class DefaultApiClient implements ApiClient {

    private ObjectMapper objectMapper = new ObjectMapper();

    private String serverUrl;

    /**
     * 数据传输过程中数据包之间间隔的最大时间
     */
    private int socketTimeout = 10;

    /**
     * 连接建立时间，三次握手完成时间
     */
    private int connectTimeout = 10;

    /**
     * 从连接池获取连接的超时时间
     */
    private int connectionRequestTimeout = 6000;

    private String encryptType = null;

    private String encryptKey = null;

    private String contentType = "application/x-www-form-urlencoded";

    public UserToken login(String username, String password) {

        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("username", username));
        params.add(new BasicNameValuePair("password", password));

        try {
            ApiResult<UserToken> resp = send(getServerUrl() + "/login" ,params, UserToken.class);

            if ("0000".equals(resp.getCode()) ) {
                return resp.getData();
            }

            return null;

        } catch (Exception e) {
            throw new ApiException(e);
        }

    }


    public <T> T callApi(String accessToken, String businessId, Map<String, Object> params, Class<T> clazz) {

        List<NameValuePair> nvplist = new ArrayList<>();
        nvplist.add( new BasicNameValuePair("accessToken", accessToken));
        nvplist.add( new BasicNameValuePair("businessId", businessId));

        String data = null;

        if(encryptType != null) {
            try {
                data = EncryptUtil.encrypt(data, encryptType, encryptKey);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {

        }

        nvplist.add( new BasicNameValuePair("params", data));

        try {
            ApiResult<T> resp = send(getServerUrl() + "/api" ,nvplist, clazz);
            if ("0000".equals(resp.getCode()) ) {
                return resp.getData();
            }

            return null;

        } catch (Exception e) {
            throw new ApiException(e);
        }

    }

    public UserToken refreshToken(String refreshToken) {

        List<NameValuePair> nvplist = new ArrayList<>();
        nvplist.add( new BasicNameValuePair("refreshToken", refreshToken));
        try {
            ApiResult resp = send(getServerUrl() + "/refreshToken" , nvplist, UserToken.class);
            return null;

        } catch (Exception e) {
            throw new ApiException(e);
        }
    }

    public <T> ApiResult<T> send(String api, List<NameValuePair> params, Class<T> clazz) throws Exception {
        try {

            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(api);
            httpPost.setHeader("Content-Type", contentType);

            RequestConfig con= RequestConfig.custom()
                    .setSocketTimeout(socketTimeout)
                    .setConnectTimeout(connectTimeout)
                    .setConnectionRequestTimeout(connectionRequestTimeout)
                    .build();
            httpPost.setConfig(con);

            httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpPost);
            JsonNode node = null;
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                //responseContent = EntityUtils.toString(entity, "UTF-8");

                ObjectMapper objectMapper = new ObjectMapper();
                ApiResult result = objectMapper.readValue(entity.getContent(), ApiResult.class);


                return result;
            }

            response.close();

            return null;
        } catch (Exception e) {
            throw new ApiException(e);
        }
    }



    public String getServerUrl() {
        return serverUrl;
    }

    public void setServerUrl(String serverUrl) {
        this.serverUrl = serverUrl;
    }

    public int getSocketTimeout() {
        return socketTimeout;
    }

    public void setSocketTimeout(int socketTimeout) {
        this.socketTimeout = socketTimeout;
    }

    public int getConnectTimeout() {
        return connectTimeout;
    }

    public void setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    public int getConnectionRequestTimeout() {
        return connectionRequestTimeout;
    }

    public void setConnectionRequestTimeout(int connectionRequestTimeout) {
        this.connectionRequestTimeout = connectionRequestTimeout;
    }

    public String getEncryptType() {
        return encryptType;
    }

    public void setEncryptType(String encryptType) {
        this.encryptType = encryptType;
    }

    public String getEncryptKey() {
        return encryptKey;
    }

    public void setEncryptKey(String encryptKey) {
        this.encryptKey = encryptKey;
    }

    public String getContentType() {
        return contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }
}
